/******************************************************************************
*File   : LogFile.h
*Author : Lan Hu
*Email	: Hi_Blue@126.com
*Notes	:
*Licence: 
*Created: 2009-09-20
*******************************************************************************/

#ifndef _MYLIB_LOGFILE_H_INCLUDE_200090920_
#define _MYLIB_LOGFILE_H_INCLUDE_200090920_

#include "public.h"
#include "File.h"
#include "Directory.h"
#include "Time.h"
#include "Timer.h"

M_BEGIN_NAMESPACE(mylib)

class LogFile
{
public:
	enum E_LOG_LEVEL
	{
		E_LOG_LEVEL_INFO,
		E_LOG_LEVEL_DEBUG,
		E_LOG_LEVEL_WARN,
		E_LOG_LEVEL_ERROR,
		E_LOG_LEVEL_FATAL
	};
	enum { E_UNINITIALIZED,E_INITIALIZED };
	enum { E_MAX_LOGPATH_LEN = 32,E_MAX_FILENAME_LEN = 64 };

private:
	byte m_State;
	Time::T_TIME_T m_RetentionTime;
	Timer m_Timer;
	ThreadMutex m_Mutex;
	char * m_Format;
	char m_LogPath[E_MAX_LOGPATH_LEN];
	char m_FileName[E_MAX_FILENAME_LEN];

public:
	LogFile()
	{
		Directory::GetPath(m_LogPath,E_MAX_LOGPATH_LEN,"./log/");
		Directory::Create(m_LogPath);
		m_Timer.setTimer(onTimer,this);
		m_RetentionTime = 7 * M_ONE_DAY_TOTAL_SEC;
		m_Timer.setInterval(1,E_DAY);
		m_Timer.start();
	}

	LogFile(char *szPath)
	{
		Directory::GetPath(m_LogPath,E_MAX_LOGPATH_LEN,szPath);
		Directory::Create(m_LogPath);
		m_Timer.setTimer(onTimer,this);
		Directory::Create(m_LogPath);
		m_Timer.setTimer(onTimer,this);
		m_RetentionTime = 7 * M_ONE_DAY_TOTAL_SEC;
		m_Timer.setInterval(1,E_DAY);
		m_Format = "L%Y%M%D%h.log";
		m_Timer.start();
	}

	LogFile(int iRetentionTime ,E_TIME_UNIT unit)
	{
		m_State=E_INITIALIZED;
		Directory::GetPath(m_LogPath,E_MAX_LOGPATH_LEN,"./log/");
		Directory::Create(m_LogPath);
		m_Timer.setTimer(onTimer,this);
		switch (unit)
		{
		case E_DAY:
			m_RetentionTime = iRetentionTime * M_ONE_DAY_TOTAL_SEC;
			m_Timer.setInterval(1,E_DAY);
			m_Format = "L%Y%M%D%h.log";
			break;
		case E_HOUR:
			m_RetentionTime = iRetentionTime * M_ONE_HOR_TOTAL_SEC;
			m_Timer.setInterval(1,E_HOUR);
			m_Format = "L%Y%M%D%h.log";
			break;
		case E_MINUTE:
			m_RetentionTime = iRetentionTime * M_ONE_MIN_TOTAL_SEC;
			m_Timer.setInterval(1,E_MINUTE);
			m_Format = "L%Y%M%D%h%m.log";
			break;
		case E_SECOND:
			m_RetentionTime = iRetentionTime ;
			m_Timer.setInterval(1,E_SECOND);
			m_Format = "L%Y%M%D%h%m%s.log";
			break;
		default:
			M_ERROR("TIME_UNIT:%d",(int)unit);
		}
		m_Timer.start();
	}

	LogFile(char *szPath,int iRetentionTime ,E_TIME_UNIT unit)
	{
		m_State=E_INITIALIZED;
		Directory::GetPath(m_LogPath,E_MAX_LOGPATH_LEN,szPath);
		Directory::Create(m_LogPath);
		m_Timer.setTimer(onTimer,this);
		switch (unit)
		{
		case E_DAY:
			m_RetentionTime = iRetentionTime * M_ONE_DAY_TOTAL_SEC;
			m_Timer.setInterval(1,E_DAY);
			m_Format = "L%Y%M%D%h.log";
			break;
		case E_HOUR:
			m_RetentionTime = iRetentionTime * M_ONE_HOR_TOTAL_SEC;
			m_Timer.setInterval(1,E_HOUR);
			m_Format = "L%Y%M%D%h.log";
			break;
		case E_MINUTE:
			m_RetentionTime = iRetentionTime * M_ONE_MIN_TOTAL_SEC;
			m_Timer.setInterval(1,E_MINUTE);
			m_Format = "L%Y%M%D%h%m.log";
			break;
		case E_SECOND:
			m_RetentionTime = iRetentionTime ;
			m_Timer.setInterval(1,E_SECOND);
			m_Format = "L%Y%M%D%h%m%s.log";
			break;
		default:
			M_ERROR("TIME_UNIT:%d",(int)unit);
		}
		m_Timer.start();
	}

	~LogFile()
	{
		m_Mutex.lock();
		m_Timer.kill();
		m_Mutex.unlock();
	}

	char* getFileName(Time::T_TIME_T iTime)
	{
		assert(m_FileName);
		char szName[32]={0};
		Time::Format(m_Format,szName,iTime);
		snprintf(m_FileName,E_MAX_FILENAME_LEN,"%s%s",m_LogPath,szName);
		return m_FileName;
	}

	char* getFileName(char *szFileName ,Time::T_TIME_T iTime)
	{
		assert(szFileName);
		char szName[32]={0};
		Time::Format(m_Format,szName,iTime);
		snprintf(szFileName,E_MAX_FILENAME_LEN,"%s%s",m_LogPath,szName);
		return szFileName;
	}

	void write(char *szLog)
	{
		char szTime[32]={0};
		Time::T_TIME_T iTime = Time::GetCurrTime();
		Time::Format("[%Y%M%D %h:%m:%s] ",szTime,iTime);
		m_Mutex.lock();
		File::T_FILE* pFile = File::Open(getFileName(iTime),"a+");
		if (pFile)
		{
			File::PutString(szTime,pFile);
			File::PutString(szLog,pFile);
			File::PutChar('\n',pFile);
			File::Close(pFile);
		}
		else
		{
			M_WARNING("Can't open the file:%s" ,m_FileName);
			int iRt = Directory::Access(m_LogPath);
			if (iRt < 0)
			{
				Directory::Create(m_LogPath);
			}
		}
		
		m_Mutex.unlock();
	}

	void operator () (char * szLog)
	{
		write(szLog);
	}

	static  void M_CDEFCALL onTimer(void * arg)
	{
		LogFile* pThis = (LogFile*)arg;
		Time::T_TIME_T iTime = Time::GetCurrTime();
		char szFileName[32]={0};
		pThis->getFileName(iTime);
		File::Create(pThis->m_FileName);
		M_TRACE("Create LogFile:%s",pThis->m_FileName);
		iTime -= pThis->m_RetentionTime;
		pThis->getFileName(szFileName,iTime);
		File::Remove(szFileName);
		M_TRACE("Remove LogFile:%s",szFileName);
	}
};


M_END_NAMESPACE(mylib)

#endif//_MYLIB_LOGFILE_H_INCLUDE_200090920_
